﻿
namespace Sai.Core.Introspection
{
    using System;

    public class FullyQualifiedName : IComparable<FullyQualifiedName>
    {
        public FullyQualifiedName(string full)
        {
            if (string.IsNullOrEmpty(full))
                throw new ArgumentNullException();

            this.Namespace = new Namespace(full.NamespaceOf());
            this.Name = new Name(full.NameWithoutNamespace());
        }

        public FullyQualifiedName(Namespace namespaceName, Name typeName)
        {
            this.Namespace = namespaceName;
            this.Name = typeName;
        }

        public Namespace Namespace
        {
            get;
            set;
        }

        public Name Name
        {
            get;
            set;
        }

        public static bool operator ==(FullyQualifiedName a, FullyQualifiedName b)
        {
            if (object.ReferenceEquals(a, b))
            {
                return true;
            }

            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }

            return a.Namespace == b.Namespace && a.Name == b.Name;
        }

        public static bool operator !=(FullyQualifiedName a, FullyQualifiedName b)
        {
            return !(a == b);
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            FullyQualifiedName another = obj as FullyQualifiedName;

            if ((object)another == null)
            {
                return false;
            }

            return this.Namespace == another.Namespace && this.Name == another.Name;
        }

        public override string ToString()
        {
            if (this.Namespace == null || String.IsNullOrEmpty(this.Namespace.Name))
                return this.Name.ToString();

            if (this.Namespace == Namespace.GlobalNamespace)
                return this.Name.ToString();

            return string.Format("{0}.{1}", this.Namespace, this.Name);
        }

        public override int GetHashCode()
        {
            return this.Namespace.GetHashCode() ^ this.Name.GetHashCode();
        }

        public int CompareTo(FullyQualifiedName other)
        {
            if (other == null)
            {
                return 1;
            }

            if (this.Namespace != other.Namespace)
            {
                return this.Namespace.CompareTo(other.Namespace);
            }

            return this.Name.CompareTo(other.Name);
        }


        public static FullyQualifiedName ConvertTypeAlias(FullyQualifiedName fullyQualifiedName)
        {
			const string SystemDotObject = "Object";
			const string ObjectAlias = "object";
			const string SystemDotBoolean = "Boolean";
			const string BooleanAlias = "bool";
			const string SystemDotString = "String";
			const string StringAlias = "string";
			const string SystemDotDouble = "Double";
			const string DoubleAlias = "double";
			const string SystemDotInt32 = "Int32";
			const string IntAlias = "int";
			const string SystemDotInt64 = "Int64";
			const string LongAlias = "long";
			const string SystemDotVoid = "Void";
			const string VoidAlias = "void";

            if (fullyQualifiedName.Namespace == Namespace.SystemNamespace)
            {
                Name convertedName = fullyQualifiedName.Name;

                switch (fullyQualifiedName.Name.Value)
                {
                    case SystemDotObject:

                        convertedName = new Name(ObjectAlias);
                        break;

                    case SystemDotBoolean:

                        convertedName = new Name(BooleanAlias);
                        break;

                    case SystemDotString:

                        convertedName = new Name(StringAlias);
                        break;

                    case SystemDotDouble:

                        convertedName = new Name(DoubleAlias);
                        break;

                    case SystemDotInt32:

                        convertedName = new Name(IntAlias);
                        break;

                    case SystemDotInt64:

                        convertedName = new Name(LongAlias);
                        break;

                    case SystemDotVoid:

                        convertedName = new Name(VoidAlias);
                        break;
                }

                return fullyQualifiedName.Namespace + convertedName;
            }

            return fullyQualifiedName;
        }

    }
}
